/*
 * s3c2410_usb.h
 *
 * Public interface to the s3c2410 USB core. For use by client modules
 * like usb-eth and usb-char.
 *
 */

#ifndef _S3C2410_USB_H
#define _S3C2410_USB_H

#include "types.h"
#include <asm/byteorder.h>

//#define USE_USBD_DMA 0
#undef USE_USBD_DMA

#if 0

typedef void (*usb_callback_t)(int flag, int size);

/* in usb_ctl.c (see also descriptor methods at bottom of file) */

// Open the USB client for client and initialize data structures
// to default values, but _do not_ start UDC.
int s3c2410_usb_open( const char * client_name );

// Start UDC running
int s3c2410_usb_start( void );

// Immediately stop udc, fire off completion routines w/-EINTR
int s3c2410_usb_stop( void ) ;

// Disconnect client from usb core
int s3c2410_usb_close( void ) ;

// set notify callback for when core reaches configured state
// return previous pointer (if any)
typedef void (*usb_notify_t)(void);
usb_notify_t s3c2410_set_configured_callback( usb_notify_t callback );

/* in usb_send.c */
int s3c2410_usb_xmitter_avail( void );
int s3c2410_usb_send(char *buf, int len, usb_callback_t callback);
void s3c2410_usb_send_reset(void);

/* in usb_recev.c */
int s3c2410_usb_recv(char *buf, int len, usb_callback_t callback);
void s3c2410_usb_recv_reset(void);

//////////////////////////////////////////////////////////////////////////////
// Descriptor Management
//////////////////////////////////////////////////////////////////////////////

#define DescriptorHeader \
    __u8 bLength;        \
    __u8 bDescriptorType


// --- Device Descriptor -------------------

typedef struct {
     DescriptorHeader;
     __u16 bcdUSB;               /* USB specification revision number in BCD */
     __u8  bDeviceClass;    /* USB class for entire device */
     __u8  bDeviceSubClass; /* USB subclass information for entire device */
     __u8  bDeviceProtocol; /* USB protocol information for entire device */
     __u8  bMaxPacketSize0; /* Max packet size for endpoint zero */
     __u16 idVendor;        /* USB vendor ID */
     __u16 idProduct;       /* USB product ID */
     __u16 bcdDevice;       /* vendor assigned device release number */
     __u8  iManufacturer;    /* index of manufacturer string */
     __u8  iProduct;        /* index of string that describes product */
     __u8  iSerialNumber;    /* index of string containing device serial number */
     __u8  bNumConfigurations; /* number fo configurations */
} __attribute__ ((packed)) device_desc_t;

// --- Configuration Descriptor ------------

typedef struct {
     DescriptorHeader;
     __u16 wTotalLength;        /* total # of bytes returned in the cfg buf 4 this cfg */
     __u8  bNumInterfaces;      /* number of interfaces in this cfg */
     __u8  bConfigurationValue; /* used to uniquely ID this cfg */
     __u8  iConfiguration;      /* index of string describing configuration */
     __u8  bmAttributes;        /* bitmap of attributes for ths cfg */
     __u8  MaxPower;            /* power draw in 2ma units */
} __attribute__ ((packed)) config_desc_t;

// bmAttributes:
enum { USB_CONFIG_REMOTEWAKE=0x20, USB_CONFIG_SELFPOWERED=0x40,
       USB_CONFIG_BUSPOWERED=0x80 };
// MaxPower:
#define USB_POWER( x)  ((x)>>1) /* convert mA to descriptor units of A for MaxPower */

// --- Interface Descriptor ---------------

typedef struct {
     DescriptorHeader;
     __u8  bInterfaceNumber;   /* Index uniquely identfying this interface */
     __u8  bAlternateSetting;  /* ids an alternate setting for this interface */
     __u8  bNumEndpoints;      /* number of endpoints in this interface */
     __u8  bInterfaceClass;    /* USB class info applying to this interface */
     __u8  bInterfaceSubClass; /* USB subclass info applying to this interface */
     __u8  bInterfaceProtocol; /* USB protocol info applying to this interface */
     __u8  iInterface;         /* index of string describing interface */
} __attribute__ ((packed)) intf_desc_t;

// --- Endpoint  Descriptor ---------------

typedef struct {
     DescriptorHeader;
     __u8  bEndpointAddress;  /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
     __u8  bmAttributes;      /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
     __u16 wMaxPacketSize;    /* data payload size for this ep in this cfg */
     __u8  bInterval;         /* polling interval for this ep in this cfg */
} __attribute__ ((packed)) ep_desc_t;

// bEndpointAddress:
/*
 *  bEndpointAddress[0:7]
 *      [0:3] - The endpoint number
 *    [4:6] - Reserved, reset to zero
 *    [7]   - Direction, ignored for contol endpoint
 *        0 = OUT endpoint
 *        1 = IN endpoint
 *   shawn
 */
enum { USB_OUT=0, USB_IN=1 };



#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
// bmAttributes:
enum { USB_EP_CNTRL=0, USB_EP_BULK=2, USB_EP_INT=3 };

// --- String Descriptor -------------------

typedef struct {
     DescriptorHeader;
     __u16 bString[1];          /* unicode string .. actaully 'n' __u16s */
} __attribute__ ((packed)) string_desc_t;

/*=======================================================
 * Handy helpers when working with above
 *
 */
// these are x86-style 16 bit "words" ...
#define make_word_c( w ) __constant_cpu_to_le16(w)
#define make_word( w )   __cpu_to_le16(w)

// descriptor types
enum { USB_DESC_DEVICE=1, USB_DESC_CONFIG=2, USB_DESC_STRING=3,
       USB_DESC_INTERFACE=4, USB_DESC_ENDPOINT=5 };


/*=======================================================
 * Default descriptor layout for S3C2410 UDC
 */

/* "config descriptor buffer" - that is, one config,
   ..one interface and 2 endpoints */
struct cdb {
     config_desc_t cfg;
     intf_desc_t   intf;
     ep_desc_t     ep1; // DOWN stream(OUT), 64byte BULK)
     ep_desc_t     ep2; // UP stream(IN), 64byte BULK)
} __attribute__ ((packed));


/* all S3C2410 device descriptors */
typedef struct {
     device_desc_t dev;   /* device descriptor */
     struct cdb b;        /* bundle of descriptors for this cfg */
} __attribute__ ((packed)) desc_t;

#endif

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
#define USB_SPEED_FULL    1
#define USB_SPEED_HIGH    2

#define MAX_CONFIGS    3
#define MAX_INTERFACES    2
#define MAX_ENDPOINTS    4


typedef void (*usb_callback_t)(int flag, int size);

/* in usb_ctl.c (see also descriptor methods at bottom of file) */

// Open the USB client for client and initialize data structures
// to default values, but _do not_ start UDC.
int pxa_usb_open( const char * client_name );

// Start UDC running
int pxa_usb_start( void );

// Immediately stop udc, fire off completion routines w/-EINTR
int pxa_usb_stop( void ) ;

// Disconnect client from usb core
int pxa_usb_close( void ) ;

// set notify callback for when core reaches configured state
// return previous pointer (if any)
typedef void (*usb_notify_t)(void);
usb_notify_t pxa_set_configured_callback( usb_notify_t callback );

/* in usb_send.c */
int pxa_usb_xmitter_avail( void );
int pxa_usb_send(char *buf, int len, usb_callback_t callback);
void sa110a_usb_send_reset(void);

/* in usb_recev.c */
int pxa_usb_recv(char *buf, int len, usb_callback_t callback);
void pxa_usb_recv_reset(void);

//////////////////////////////////////////////////////////////////////////////
// Descriptor Management
//////////////////////////////////////////////////////////////////////////////

#define DescriptorHeader \
    __u8 bLength;        \
    __u8 bDescriptorType


// --- Device Descriptor -------------------

typedef struct {
     DescriptorHeader;
     __u16 bcdUSB;               /* USB specification revision number in BCD */
     __u8  bDeviceClass;    /* USB class for entire device */
     __u8  bDeviceSubClass; /* USB subclass information for entire device */
     __u8  bDeviceProtocol; /* USB protocol information for entire device */
     __u8  bMaxPacketSize0; /* Max packet size for endpoint zero */
     __u16 idVendor;        /* USB vendor ID */
     __u16 idProduct;       /* USB product ID */
     __u16 bcdDevice;       /* vendor assigned device release number */
     __u8  iManufacturer;    /* index of manufacturer string */
     __u8  iProduct;        /* index of string that describes product */
     __u8  iSerialNumber;    /* index of string containing device serial number */
     __u8  bNumConfigurations; /* number fo configurations */
} __attribute__ ((packed)) device_desc_t;

// --- Configuration Descriptor ------------

typedef struct {
     DescriptorHeader;
     __u16 wTotalLength;        /* total # of bytes returned in the cfg buf 4 this cfg */
     __u8  bNumInterfaces;      /* number of interfaces in this cfg */
     __u8  bConfigurationValue; /* used to uniquely ID this cfg */
     __u8  iConfiguration;      /* index of string describing configuration */
     __u8  bmAttributes;        /* bitmap of attributes for ths cfg */
     __u8  MaxPower;            /* power draw in 2ma units */
} __attribute__ ((packed)) config_desc_t;

// bmAttributes:
enum {
    USB_CONFIG_REMOTEWAKE=0xA0,
    USB_CONFIG_SELFPOWERED=0xC0,
    USB_CONFIG_BUSPOWERED=0x80
};

// MaxPower:
#define USB_POWER( x)  ((x)>>1) /* convert mA to descriptor units of A for MaxPower */

// --- Interface Descriptor ---------------

typedef struct {
     DescriptorHeader;
     __u8  bInterfaceNumber;   /* Index uniquely identfying this interface */
     __u8  bAlternateSetting;  /* ids an alternate setting for this interface */
     __u8  bNumEndpoints;      /* number of endpoints in this interface */
     __u8  bInterfaceClass;    /* USB class info applying to this interface */
     __u8  bInterfaceSubClass; /* USB subclass info applying to this interface */
     __u8  bInterfaceProtocol; /* USB protocol info applying to this interface */
     __u8  iInterface;         /* index of string describing interface */
} __attribute__ ((packed)) intf_desc_t;

// --- Endpoint  Descriptor ---------------

typedef struct {
     DescriptorHeader;
     __u8  bEndpointAddress;  /* 0..3 ep num, bit 7: 0 = 0ut 1= in */
     __u8  bmAttributes;      /* 0..1 = 0: ctrl, 1: isoc, 2: bulk 3: intr */
     __u16 wMaxPacketSize;    /* data payload size for this ep in this cfg */
     __u8  bInterval;         /* polling interval for this ep in this cfg */
} __attribute__ ((packed)) ep_desc_t;

// bEndpointAddress:
enum {
    USB_OUT    =0,
    USB_IN    =1
};

#define USB_EP_ADDRESS(a,d) (((a)&0xf) | ((d) << 7))
// bmAttributes:
enum {
    USB_EP_CNTRL    =0,
    USB_EP_BULK    =2,
    USB_EP_INT    =3,
    USB_EP_ISO    =4
};

/*
 * Device and/or Interface Class codes
 * as found in bDeviceClass or bInterfaceClass
 * and defined by www.usb.org documents
 */
#define USB_CLASS_PER_INTERFACE    0    /* for DeviceClass */
#define USB_CLASS_AUDIO            1
#define USB_CLASS_COMM            2
#define USB_CLASS_HID            3
#define USB_CLASS_PHYSICAL        5
#define USB_CLASS_STILL_IMAGE    6
#define USB_CLASS_PRINTER        7
#define USB_CLASS_MASS_STORAGE  8
#define USB_CLASS_HUB            9
#define USB_CLASS_CDC_DATA        0x0a
#define USB_CLASS_CSCID            0x0b    /* chip+ smart card */
#define USB_CLASS_CONTENT_SEC   0x0d    /* content security */
#define USB_CLASS_VIDEO            0x0e
#define USB_CLASS_APP_SPEC        0xfe
#define USB_CLASS_VENDOR_SPEC    0xff

// --- String Descriptor -------------------

typedef struct {
     DescriptorHeader;
     __u16 bString[1];          /* unicode string .. actaully 'n' __u16s */
} __attribute__ ((packed)) string_desc_t;

// --- Device Qualifier Descriptor ---------------

typedef struct  {
    __u8  bLength;
    __u8  bDescriptorType;

    __u16 bcdUSB;
    __u8  bDeviceClass;
    __u8  bDeviceSubClass;
    __u8  bDeviceProtocol;
    __u8  bMaxPacketSize0;
    __u8  bNumConfigurations;
    __u8  bRESERVED;
} __attribute__ ((packed)) qua_desc_t;

#define ELR_PACKED __attribute__ ((packed))
/* CDC-ACM Defines and Structures */

#define USB_CDC_SUBCLASS_ACM            2

#define USB_CDC_CTRL_PROTO_NONE            0
#define USB_CDC_CTRL_PROTO_AT            1
#define USB_CDC_CTRL_PROTO_VENDOR        0xff

#define USB_CDC_HEADER            0x00
#define USB_CDC_CALL_MGMT        0x01
#define USB_CDC_ACM                0x02
#define USB_CDC_UNION            0x06

#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT        0x01
#define USB_CDC_CALL_MGMT_CAP_DATA_INTF        0x02

#define USB_CDC_REQ_SET_LINE_CODING        0x20
#define USB_CDC_REQ_GET_LINE_CODING        0x21
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE    0x22

#define USB_CDC_1_STOP_BITS            0
#define USB_CDC_1_5_STOP_BITS        1
#define USB_CDC_2_STOP_BITS            2

#define USB_CDC_NO_PARITY            0
#define USB_CDC_ODD_PARITY            1
#define USB_CDC_EVEN_PARITY            2
#define USB_CDC_MARK_PARITY            3
#define USB_CDC_SPACE_PARITY        4

/* CDC specific */
#define GET_LINE_CODING           0x21
#define SET_LINE_CODING           0x20
#define SET_CONTROL_LINE_STATE    0x22
#define SEND_BREAK                0x23
#define SEND_ENCAPSULATED_COMMAND 0x00
#define GET_ENCAPSULATED_COMMAND  0x01


#define GS_NUM_CONFIGS            1
#define GS_NO_CONFIG_ID            0
#define GS_BULK_CONFIG_ID        1
#define GS_ACM_CONFIG_ID        2

#define GS_MAX_NUM_INTERFACES        2
#define GS_BULK_INTERFACE_ID        0
#define GS_CONTROL_INTERFACE_ID        0
#define GS_DATA_INTERFACE_ID        1

#define GS_DEFAULT_DTE_RATE        115200
#define GS_DEFAULT_DATA_BITS    8
#define GS_DEFAULT_PARITY        USB_CDC_NO_PARITY
#define GS_DEFAULT_CHAR_FORMAT  USB_CDC_1_STOP_BITS

#define LINE_CODE_LEN 7
/* conventional codes for class-specific descriptors */
#define USB_DT_CS_DEVICE        0x21
#define USB_DT_CS_CONFIG        0x22
#define USB_DT_CS_STRING        0x23
#define USB_DT_CS_INTERFACE        0x24
#define USB_DT_CS_ENDPOINT        0x25

typedef struct ELR_PACKED __usb_cdc_header_desc {
    unsigned char    bLength;
    unsigned char    bDescriptorType;
    unsigned char    bDescriptorSubType;
    unsigned short     bcdCDC;
}usb_cdc_header_desc, *Pusb_cdc_header_desc;

/* Call Management Descriptor from CDC spec 5.2.3.3 */
typedef struct ELR_PACKED __usb_cdc_call_mgmt_desc {
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bDescriptorSubType;
    unsigned char  bmCapabilities;
    unsigned char  bDataInterface;
}usb_cdc_call_mgmt_desc, *Pusb_cdc_call_mgmt_desc;

/* Abstract Control Management Descriptor from CDC spec 5.2.3.4 */
typedef struct ELR_PACKED __usb_cdc_acm_desc {
    unsigned char  bLength;
    unsigned char  bDescriptorType;
    unsigned char  bDescriptorSubType;
    unsigned char  bmCapabilities;
}usb_cdc_acm_desc, *Pusb_cdc_acm_desc;

/* Union Functional Descriptor from CDC spec 5.2.3.8 */
typedef struct ELR_PACKED __usb_cdc_union_desc {
    unsigned char    bLength;
    unsigned char    bDescriptorType;
    unsigned char    bDescriptorSubType;
    unsigned char    bMasterInterface0;
    unsigned char    bSlaveInterface0;
    /* ... and there could be other slave interfaces */
}usb_cdc_union_desc, *Pusb_cdc_union_desc;

/* Line Coding Structure from CDC spec 6.2.13 */
typedef struct ELR_PACKED __usb_cdc_line_coding {
    unsigned int dwDTERate;
    unsigned char bCharFormat;
    unsigned char bParityType;
    unsigned char bDataBits;
}usb_cdc_line_coding, *Pusb_cdc_line_coding;

typedef struct ELR_PACKED __gs_acm_fullspeed_function {
    //usb_cdc_header_desc    gs_header_desc;
    usb_cdc_call_mgmt_desc gs_call_mgmt_descriptor;
    usb_cdc_acm_desc       gs_acm_descriptor;
    usb_cdc_union_desc     gs_union_desc;
    ep_desc_t    gs_fullspeed_notify_desc;
} acm_function, *Pacm_function;

typedef struct ELR_PACKED _NOTIFY {
    unsigned char bmRequest, bNotifucation;
    unsigned short wValue, wIndex, wLength, Data;
} SER_NOTIFY, *PSER_NOTIFY;

/*=======================================================
 * Handy helpers when working with above
 *
 */
// these are x86-style 16 bit "words" ...
#define make_word_c( w ) __constant_cpu_to_le16(w)
#define make_word( w )   __cpu_to_le16(w)

// descriptor types
enum {
    USB_DESC_DEVICE    = 1,
    USB_DESC_CONFIG    = 2,
    USB_DESC_STRING    = 3,
    USB_DESC_INTERFACE    = 4,
    USB_DESC_ENDPOINT    = 5,
    USB_DESC_QUALIFIER    = 6,
    USB_DESC_OTHER_SPEED_CONFIG = 7
};


/*=======================================================
 * Default descriptor layout for SA-1100 and SA-1110 UDC
 */

enum {
  UNUSED = 0,

  BULK_IN1  =  1,
  BULK_OUT1 =  2,
  ISO_IN1   =  3,
  ISO_OUT1  =  4,
  INT_IN1   =  5,

  BULK_IN2  =  6,
  BULK_OUT2 =  7,
  ISO_IN2   =  8,
  ISO_OUT2  =  9,
  INT_IN2   = 10,

  BULK_IN3  = 11,
  BULK_OUT3 = 12,
  ISO_IN3   = 13,
  ISO_OUT3  = 14,
  INT_IN3   = 15
} /*endpoint_type*/;

/* "config descriptor buffer" - that is, one config,
   ..one interface and 2 endpoints */
//struct cdb {
//     config_desc_t cfg;
//     intf_desc_t   intf;
//     ep_desc_t     ep1;
//     ep_desc_t     ep2;
//} __attribute__ ((packed));

/* all SA device descriptors */
//typedef struct {
//     device_desc_t dev;   /* device descriptor */
//     struct cdb b;        /* bundle of descriptors for this cfg */
//} __attribute__ ((packed)) desc_t;


typedef struct {
    device_desc_t     dev;    /* device descriptor */
    char        cdb[1024]; /* FIXME */
    qua_desc_t    qua;

} desc_t;


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

/*=======================================================
 * Descriptor API
 */

/* Get the address of the statically allocated desc_t structure
   in the usb core driver. Clients can modify this between
   the time they call s3c2410_usb_open() and s3c2410_usb_start()
*/
desc_t *
s3c2410_usb_get_descriptor_ptr( void );


/* Set a pointer to the string descriptor at "index". The driver
 ..has room for 8 string indicies internally. Index zero holds
 ..a LANGID code and is set to US English by default. Inidices
 ..1-7 are available for use in the config descriptors as client's
 ..see fit. This pointer is assumed to be good as long as the
 ..S3C2410 usb core is open (so statically allocate them). Returnes -EINVAL
 ..if index out of range */
int s3c2410_usb_set_string_descriptor( int index, string_desc_t * p );

/* reverse of above */
string_desc_t *
s3c2410_usb_get_string_descriptor( int index );

/* kmalloc() a string descriptor and convert "p" to unicode in it */
string_desc_t *
s3c2410_usb_kmalloc_string_descriptor( const char * p );

#endif /* _S3C2410_USB_H */
